#include "PrintTable.h"

#define CORNER_FLAG "+"
#define ROW_LINE "-"
#define COL_PADDING " "
#define COL_LINE "|"

/**
* 计算在控制台中输出的字符串长度
* str 字符串
**/
static int str_len(unsigned char *str)
{
    int len = 0;
    int offset = 2;
    int word_len = strlen(str);
    int i = 0;

    for (i; i < word_len; i++)
    {
        if (str[i] < 128)
        {
            len += 1;
        }
        else
        {
            len += 2;
            i += offset;
        }
    }
    return len;
}
/**
* 生成表格行边
* col_width 表格的列宽
* col_num 表格列数
* edge 保存行边字符串
**/
static void make_edge(const unsigned int *col_width, const unsigned int col_num, char *edge)
{
    memset(edge, 0, sizeof(edge));
    strcat(edge, CORNER_FLAG);
    int col_line_counter;
    int row_line_counter;
    for (col_line_counter = 0; col_line_counter < col_num; col_line_counter++)
    {
        strcat(edge, ROW_LINE);
        for (row_line_counter = 0; row_line_counter < col_width[col_line_counter]; row_line_counter++)
        {
            strcat(edge, ROW_LINE);
        }
        strcat(edge, ROW_LINE);
        strcat(edge, CORNER_FLAG);
    }
    strcat(edge, "\n");
}

/**
* 根据表格一列的宽度值，求出该列中最大的宽度
* col_width 指向一列所有宽度值数组的指针
* row_num 表格行数
* return 最大宽度值
**/
static int get_max_col_width(int *col_width, const unsigned int row_num)
{
    int max_col_width = 0;
    int i = 0;
    for (i; i < row_num; i++)
    {
        if (max_col_width < col_width[i])
        {
            max_col_width = col_width[i];
        }
    }
    return max_col_width;
}

/**
* 根据表格列的宽度，求出每列最大的宽度
* col_width 指向表格所有列宽度二维数组的指针
* row_num 表格行数
* col_num 表格列数
* max_col_width 指向table结构体中的col_max_width的指针，用于保存表格每列最大的宽度
**/
static void get_max_col(int **col_width, const unsigned int row_num, const unsigned int col_num, int *max_col_width)
{
    int i;
    int j;
    for (i = 0; i < col_num; i++)
    {
        int max_width[ row_num ];
        for (j = 0; j < row_num; j++)
        {
            max_width[j] = *((int *)col_width + (j * col_num) + i);
        }
        max_col_width[i] = get_max_col_width(max_width, row_num);
    }
}

/**
* 得到表格中所有列的宽度值
* t 指向表格结构体的指针
* col_width 指向表格所有列宽度二维数组的指针，用于保存所有宽度值
**/
static void get_col_width(table *t, int **col_width)
{
    int i = 0;
    int j;
    for (i; i < t->row_num; i++)
    {
        for (j = 0; j < t->col_num; j++)
        {
            *((int *)col_width + i * t->col_num + j) = str_len(t->content[i][j]);
        }
    }
}

/**
* 设置table结构体中col_max_width
* t 指向表格结构体的指针
**/
static void set_table_col_max_width(table *t)
{
    int col_width[t->row_num][t->col_num];
    get_col_width(t, (int **)col_width);
    get_max_col((int **)col_width, t->row_num, t->col_num, t->col_max_width);
}

/**
* 得到表格的总宽
* t 指向表格结构体的指针
**/
static int get_table_width(table *t)
{
    int col_padding_width = 2 * t->col_num;
    int col_line_width = t->col_num + 1;
    int col_width = 0;
    int i;
    for (i = 0; i < t->col_num; i++)
    {
        col_width += t->col_max_width[i];
    }
    return col_line_width + col_padding_width + col_width;
}

/**
* 设置格式化表格中的空格
* str 保存的字符串
* space_num 空格的数量
**/
static void set_space_txt(char *str, const unsigned int space_num)
{
    int i;
    for (i = 0; i < space_num; i++)
    {
        strcat(str, " ");
    }
}

/**
* 生成表格行边
* row_id 行id
* t 指向表格结构体的指针
* row_txt 格式化输出的表格行边字符串
**/
static void make_row(const unsigned int row_id, table *t, char *row_txt)
{
    int i;
    memset(row_txt, 0, sizeof(row_txt));
    strcat(row_txt, COL_LINE);
    for (i = 0; i < t->col_num; i++)
    {
        strcat(row_txt, COL_PADDING);
        int word_len = str_len(t->content[row_id][i]);
        strcat(row_txt, t->content[row_id][i]);
        set_space_txt(row_txt, t->col_max_width[i] - word_len);
        strcat(row_txt, COL_PADDING);
        strcat(row_txt, COL_LINE);
    }
}


/**
* 格式化表格方法
* t 指向表格结构体的指针
* formated_out 格式化输出字符串
**/
void format_table(table *t, char *formated_out)
{
    set_table_col_max_width(t);
    int col_width = get_table_width(t);
    char row_txt[col_width + t->col_num];
    int i;

    make_edge(t->col_max_width, t->col_num, row_txt);
    strcat(formated_out, row_txt);

    for (i = 0; i < t->row_num; i++)
    {
        make_row(i, t, row_txt);
        strcat(formated_out, row_txt);
        strcat(formated_out, "\n");
        make_edge(t->col_max_width, t->col_num, row_txt);
        strcat(formated_out, row_txt);
    }
}


int main()
{

    table t;
	int ix,jx;
	char aucTmpData[50];

    t.row_num = 2;
    t.col_num = 2;

    t.col_max_width = (int *)malloc(sizeof(int) * t.col_num);
    t.content = (char ***)malloc(sizeof(char **) * t.row_num);

	for(ix =0;ix<t.row_num;ix++)
	{
		t.content[ix] = (char **)malloc(sizeof(char *) * t.col_num);
    }


#if 0
	for(ix =0;ix<t.row_num;ix++)
	{
	   for(jx =0;jx<t.col_num;jx++)
		sprintf(t.content[ix][jx],"0x%02x",ix*4);
    }
#endif
	//sprintf(t.content[0][1],"Device ID:0x%04x     Vendor ID:0x%04x",ix*4);
	//sprintf(t.content[1][1],"Status :0x%04x     Vendor ID:0x%04x",ix*4);

#if 1
	char formated_out1[2048];

	sprintf(formated_out1,"%s ","12");
	t.content[0][0] = formated_out1;
	sprintf(formated_out1,"%s ","13");
    t.content[0][1] = formated_out1;
	t.content[1][0] = formated_out1;
    t.content[1][1] = formated_out1;
#endif

    char formated_out[2048];
    memset(formated_out, 0, 2048);
    format_table(&t, formated_out);
    printf("%s", formated_out);


    free(t.col_max_width);
	for(ix =0;ix<t.row_num;ix++)
	{
		free(t.content[ix]);
    }
    free(t.content);
    return 0;
}
